package com.study.spmongodb.book.wwj.char08;

import java.util.LinkedList;

/**
 * @author MI
 * @version 1.0
 * @date 2020/11/25 23:05
 */
public class LinkedRunnableQueue implements RunnableQueue {
    //任务队列的最大容量，在构造时传入
    private final int limit;

    //若线程池满了，则执行拒绝策略
    private final DenyPolicy denyPolicy;

    //存放任务的队列
    private final LinkedList<Runnable> runnableList = new LinkedList<>();

    private final ThreadPool threadPool;

    public LinkedRunnableQueue(int limit, DenyPolicy denyPolicy, ThreadPool threadPool) {
        this.limit = limit;
        this.denyPolicy = denyPolicy;
        this.threadPool = threadPool;
    }

    @Override
    public void offer(Runnable runnable) {
        synchronized (runnableList) {
            if (runnableList.size() >= limit) {
                //无法容纳新的任务时执行拒绝策略
                denyPolicy.reject(runnable, threadPool);
            } else {
                //将任务加入到队尾，并且唤醒阻塞中的线程
                runnableList.addLast(runnable);
                runnableList.notifyAll();
            }
        }

    }

    @Override
    public Runnable take() throws InterruptedException {
        synchronized (runnableList) {
            while (runnableList.isEmpty()) {
                try {
                    // 如果队列中没有课执行的任务，则当前线程将会挂起，
                    runnableList.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                    throw e;
                }
            }
            //从队列头部移除一个任务
            return runnableList.removeFirst();
        }
    }


    /**
     * 返回当前队列中的任务数
     *
     * @return
     */
    @Override
    public int size() {
        synchronized (runnableList) {
            return runnableList.size();
        }
    }
}
